use core::fmt::{Display, Formatter};
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use crate::error::Error;
use crate::modeling::Value;

#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
#[builder(name = "PromptGenerateOptionsBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct PromptGenerateOptions {
    model_config: String,
    no_variable: bool,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub enum PromptGeneratorBuildInTemplate {
    /// Agent
    #[default]
    #[serde(rename = "rule")]
    Rule,
    #[serde(rename = "code-class")]
    CodeClass,
}

#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
#[builder(name = "PromptResultBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct PromptResult {
    prompt: String,
    variables: Option<Vec<String>>,
    opening_statement: Option<String>,
    error: Option<String>,
}

#[async_trait::async_trait]
pub trait PromptGenerator {
    /// 根据数据库获取到元数据
    async fn generate_with_buildin(
        &self,
        buildin_template: PromptGeneratorBuildInTemplate,
        instruction: &String,
        options: PromptGenerateOptions,
    ) -> anyhow::Result<PromptResult>;
}
